#! /bin/bash

Pages=1024

#
# Creates hugepage filesystem.
#
create_mnt_huge()
{
	echo "Creating /mnt/huge and mounting as hugetlbfs"
	mkdir -p /mnt/huge

	grep -s '/mnt/huge' /proc/mounts > /dev/null
	if [ $? -ne 0 ] ; then
		mount -t hugetlbfs nodev /mnt/huge
	fi
}

#
# Removes hugepage filesystem.
#
remove_mnt_huge()
{
	echo "Unmounting /mnt/huge and removing directory"
	grep -s '/mnt/huge' /proc/mounts > /dev/null
	if [ $? -eq 0 ] ; then
		umount /mnt/huge
	fi

	if [ -d /mnt/huge ] ; then
		rm -R /mnt/huge
	fi
}

#
# Unloads igb_uio.ko.
#
remove_igb_uio_module()
{
	echo "Unloading any existing DPDK UIO module"
	/sbin/lsmod | grep -s igb_uio > /dev/null
	if [ $? -eq 0 ] ; then
		/sbin/rmmod igb_uio
	fi
}

#
# Loads new igb_uio.ko (and uio module if needed).
#
load_igb_uio_module()
{
	if [ ! -f ./igb_uio.ko ];then
		echo "## ERROR: Target does not have the DPDK UIO Kernel Module."
		return
	fi

	remove_igb_uio_module

	/sbin/lsmod | grep -s uio > /dev/null
	if [ $? -ne 0 ] ; then
		modinfo uio > /dev/null
		if [ $? -eq 0 ]; then
			echo "Loading uio module"
			/sbin/modprobe uio
		fi
	fi

	# UIO may be compiled into kernel, so it may not be an error if it can't
	# be loaded.

	echo "Loading DPDK UIO module"
	/sbin/insmod ./igb_uio.ko
	if [ $? -ne 0 ] ; then
		echo "## ERROR: Could not load kmod/igb_uio.ko."
		return
	fi
}

#
# Removes all reserved hugepages.
#
clear_huge_pages()
{
	for d in /sys/devices/system/node/node? ; do
		echo 0 > $d/hugepages/hugepages-2048kB/nr_hugepages
	done

	remove_mnt_huge
}

#
# Creates hugepages.
#
set_non_numa_pages()
{
	clear_huge_pages

	echo $Pages > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

	create_mnt_huge
}

#
# Creates hugepages on specific NUMA nodes.
#
set_numa_pages()
{
	clear_huge_pages

	for d in /sys/devices/system/node/node? ; do
		echo $Pages > $d/hugepages/hugepages-2048kB/nr_hugepages
	done

	create_mnt_huge
}

#
# Uses dpdk_nic_bind.py to move devices to work with igb_uio
#
bind_nics_to_igb_uio()
{
	echo "Binding $NIC"
	if  /sbin/lsmod  | grep -q igb_uio ; then
		#./dpdk_nic_bind.py --status
		./dpdk_nic_bind.py -b igb_uio $NIC && echo "OK"
	else
		echo "# Please load the 'igb_uio' kernel module before querying or "
		echo "# adjusting NIC device bindings"
	fi
}

if [ $# -lt 1 ]; then
	echo "Usage: $0 eth0 eth1 ..."
	exit 0
fi


if lscpu | grep -i -q numa; then
	set_numa_pages
else
	set_non_numa_pages
fi

load_igb_uio_module
for NIC in $1;
do
	bind_nics_to_igb_uio
done


